﻿using System;
using System.Collections.Generic;
using System.Data.Linq.Mapping;
using System.Linq;
using TruyenTranhCrawler.Utils;

namespace TruyenTranhCrawler.Data
{
    [Table]
    public class Book : BaseObject
    {
        public Book()
        {
            CreatedDate = ModifiedDate = DateTime.Now;
            Status = false;
        }
        #region properties
        [Column(IsPrimaryKey = true, IsDbGenerated = true)]
        public int ID { get; set; }

        [Column]
        public int AuthorId { get; set; }
        [Column]
        public string FullName { get; set; }

        [Column]
        public string SortName { get; set; }

        [Column]
        public string SafeName { get; set; }

        [Column]
        public string OtherName { get; set; }

        [Column]
        public string OtherSortName { get; set; }

        [Column]
        public string Description { get; set; }

        [Column]
        public string Image { get; set; }

        [Column]
        public bool Status { get; set; }

        [Column]
        public DateTime CreatedDate { get; set; }
        [Column]
        public DateTime ModifiedDate { get; set; }

        [Column]
        public string Source { get; set; }

        [Column]
        public bool Finish { get; set; }

        [Column]
        public string Types { get; set; }

        [Column]
        public string HistoryTypeIds { get; set; }

        [Column]
        public string CrawlAuthor { get; set; }
        [Column]
        public string CrawlUrl { get; set; }
        [Column]
        public string CrawlName { get; set; }
        [Column]
        public string CrawlHost { get; set; }

        [Column]
        public int LastChapId { get; set; }
        [Column]
        public int TotalChap { get; set; }
        [Column]
        public bool IsUnique { get; set; }
        #endregion

        const string ImgSizePattern = @"/(w|s|h)(\d+)/";
        public static string RenderImage(string image, int width, string title = "", bool getLinkOnly = true)
        {
            var parser = new HtmlParser();
            string link;
            string html;
            var fiximg = image ?? "";   //do not null
            var fiximglower = fiximg.ToLower();
            if (fiximglower.IndexOf("google.com") >= 0 || fiximglower.IndexOf("blogspot.com") >= 0)
            {
                var replacer = string.Format("/w{0}/", width);
                var idx = fiximg.IndexOf("?");
                if (idx > 0)
                    fiximg = fiximg.Substring(0, idx);

                link = parser.Replace(fiximg, ImgSizePattern, replacer);
                if (link.IndexOf(replacer) < 0)
                {
                    idx = link.LastIndexOf("/");
                    link = link.Insert(idx, replacer.Remove(replacer.Length - 1));
                }
                html = string.Format("<img src=\"{0}\" title=\"{1}\" width={2} />", link, title, width);
            }
            else if (fiximglower.StartsWith("http"))
            {
                link = fiximg;
                html = string.Format("<img src=\"{0}\" title=\"{1}\" width={2} />", link, title, width);
            }
            else
            {
                link = fiximg;
                html = string.Format("<img src=\"{0}\" title=\"{1}\" width={2} />", link, title, width);
            }
            return getLinkOnly ? link : html;
        }

        /// <summary>
        /// Lay danh sach Book chua finish hoac ko co bai tin nao
        /// </summary>
        /// <returns></returns>
        public static IList<Book> GetWaitingBooks()
        {
            using (var context = new CmsDataContext())
            {
                return context.Books.Where(x => !x.Finish).ToList();
            }
        }
        public override void Save()
        {
            FullName = System.Threading.Thread.CurrentThread.CurrentCulture.TextInfo.ToTitleCase(FullName.ToLower()).Trim();
            SafeName = GetSafeName(FullName);
            SortName = GetSortNameFromSafeName(SafeName);

            if (OtherName != null)
            {
                if (OtherName.Length > 500)
                    OtherName = OtherName.Substring(0, 499);

                OtherSortName = GetSortName(OtherName);
            }
            AuthorId = Author.InsertSkipExisted(CrawlAuthor);
            var typeIds = HistoryType.GetIds(Types);
            HistoryTypeIds = string.Join(",", typeIds);
            base.Save();

            if (ID > 0)
            {
                //make list BookByAuthor
                BookByAuthor.AddBook(AuthorId, ID);

                //make list BookByType
                foreach (var hid in typeIds)
                {
                    BookType.AddBook(hid, ID);
                }
            }
            else
            {
                //ghi thong tin bi loi ra day
                Logger.Error(string.Format("Fullname: {0},safename: {1}, OtherName: {2}, HistoryTypeIds: {3},image:{4},Description:{5},Types:{6},CrawlName:{7},CrawlAuthor:{8},CrawlUrl:{9}",
                    FullName.Length,SafeName.Length,(OtherName??"").Length,HistoryTypeIds.Length,Image.Length,Description.Length,Types.Length,CrawlName.Length,CrawlAuthor.Length,CrawlUrl.Length));
            }
        }
        
        /// <summary>
        /// update ModifiedData + Status=true
        /// </summary>
        /// <param name="bookId"></param>
        /// <param name="date"></param>
        public static void UpdateChanged(int bookId, DateTime date)
        {
            //update book
            using (var context = new CmsDataContext())
            {
                context.ExecuteCommand("update Book set ModifiedDate={1},Status=1 where ID={0}", bookId, date);
            }
        }
        /// <summary>
        /// Update lastChapId and ModifiedDate is now  + Status=true
        /// </summary>
        public static void UpdateLastChap(int bookId, int lastChapId, int totalChap)
        {
            //update book
            using (var context = new CmsDataContext())
            {
                context.ExecuteCommand("update Book set LastChapId={1},TotalChap={2},ModifiedDate=GETDATE(),Status=1 where ID={0}", bookId, lastChapId, totalChap);
            }
        }
        public static void UpdateStatus(int bookId, bool finish)
        {
            //update book
            using (var context = new CmsDataContext())
            {
                context.ExecuteCommand("update Book set Finish={1} where ID={0}", bookId, finish);
            }
        }
        /// <summary>
        /// Accept only not existed, or not finished
        /// </summary>
        /// <returns></returns>
        public static bool CanbeCrawl(ref Book b)
        {
            try
            {
                var sortName = GetSortName(b.FullName);
                var crawlHost = b.CrawlHost;
                List<Book> exists;
                // get list samename
                using (var context = new CmsDataContext())
                {
                    exists = context.Books.Where(x => x.SortName == sortName).ToList();
                }
                if (!exists.Any())
                    return true;

                //neu da ton tai cua nguon nay
                var check = exists.FirstOrDefault(x => x.CrawlHost == crawlHost);
                if (check != null)
                {
                    if (!check.Finish)  // chua ket thuc
                    {
                        b = check;
                        return true;
                    }
                    return false;
                }

                //neu da co 1 ban tu nguon khac thi bo qua
                return exists.Count(x => x.CrawlHost != crawlHost) <= 0;
            }
            catch (Exception ex)
            {
                Logger.Info("*** ERROR " + ex);
            }
            return false;
        }

        public static bool IsNotExisted(string crawlUrl)
        {
            using (var context = new CmsDataContext())
            {
                return context.Books.Count(x => x.CrawlUrl == crawlUrl) <= 0;
            }
        }

        public static Book FindByKey(int key)
        {
            using (var context = new CmsDataContext())
            {
                return context.Books.FirstOrDefault(x => x.ID == key);
            }
        }
    }

}
